package com.kabigon.mall.multi.common;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import com.kabigon.mall.multi.common.api.JsonResult;
import com.kabigon.mall.multi.dto.BucketPolicyConfigDto;
import com.kabigon.mall.multi.dto.MinioUploadDto;
import io.minio.*;
import io.minio.http.Method;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Minio对象存储管理Controller
 *
 * @author xu.biao
 * @version v1.0
 * @Package com.kabigon.mall.multi.common
 * @data 2022/4/10 19:23
 */
@Api(tags = "MinioController", description = "Minio对象存储管理")
@Slf4j
@RestController
@RequestMapping("/minio")
public class MinioController {
    @Value("${minio.endpoint}")
    private String endpoint;
    @Value("${minio.accessKey}")
    private String accessKey;
    @Value("${minio.secretKey}")
    private String secretKey;
    @Value("${minio.bucketName}")
    private String bucketName;

    @ApiOperation("文件上传")
    @PostMapping("/upload")
    public JsonResult upload(@RequestParam("file") MultipartFile file) {
        try {
            MinioClient minioClient = MinioClient.builder()
                    .endpoint(endpoint)
                    .credentials(accessKey, secretKey)
                    .build();
            boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!isExist) {
                // 创建存储桶并设置只读权限
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
                BucketPolicyConfigDto bucketPolicyConfigDto = createBucketPolicyConfigDto(bucketName);
                SetBucketPolicyArgs setBucketPolicyArgs = SetBucketPolicyArgs.builder()
                        .bucket(bucketName)
                        .config(JSONUtil.toJsonStr(bucketPolicyConfigDto))
                        .build();
                minioClient.setBucketPolicy(setBucketPolicyArgs);

            } else {
                log.info("存储桶已存在");
            }
            // 判断file是否存在
            Assert.isTrue(!file.isEmpty(), "文件不存在");
            String filename = file.getOriginalFilename();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            String[] split = filename.split("\\.");
            // 文件名
            // 32位时间戳+随机数+文件后缀
            filename = sdf.format(new Date()) + "_" + split[0] + "_" + IdUtil.simpleUUID() + "." + split[1];
            // 设置存储对象的名称
            String objectName = sdf.format(new Date()) + "/" + filename;
            // 使用putObject上传文件到存储桶中
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .contentType(file.getContentType())
                    .stream(file.getInputStream(), file.getSize(), ObjectWriteArgs.MIN_MULTIPART_SIZE)
                    .build();
            minioClient.putObject(putObjectArgs);
            log.info("文件上传成功");
            MinioUploadDto minioUploadDto = new MinioUploadDto();
            minioUploadDto.setFileName(filename);
            String url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .method(Method.GET)
                    .bucket(bucketName)
                    .object(objectName)
                    .build());
            minioUploadDto.setUrl(url);

            return JsonResult.success(minioUploadDto);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("文件上传失败:{}", e.getMessage());
        }
        return JsonResult.failed("文件上传失败");
    }

    private BucketPolicyConfigDto createBucketPolicyConfigDto(String bucketName) {
        BucketPolicyConfigDto.Statement statement = BucketPolicyConfigDto.Statement.builder()
                .effect("Allow")
                .action("*")
                .principal("s3.GetObject")
                .resource("arn:aws:s3:::" + bucketName + "/*.**")
                .build();
        return BucketPolicyConfigDto.builder()
                .version("2012-10-17")
                .statement(CollUtil.toList(statement))
                .build();
    }

    @ApiOperation("删除文件")
    @PostMapping("/delete")
    public JsonResult delete(@RequestParam("fileName") String fileName) {
        try {
            MinioClient minioClient = MinioClient.builder()
                    .endpoint(endpoint)
                    .credentials(accessKey, secretKey)
                    .build();
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());
            log.info("文件删除成功");
            return JsonResult.success(null);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("文件删除失败:{}", e.getMessage());
        }
        return JsonResult.failed("文件删除失败");
    }

}

